/*
*  message.c - parse msn messages
*  Copyright (c) 2005 Derek Ingrouville (dergro@users.sourceforge.net)
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Library General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include <stdlib.h>
#include <string.h>

#include "command.h"
#include "message.h"

MessageHeader *
message_header_new (const char *header)
{
	/* Header format: "name: value" */

	MessageHeader *msgheader = NULL;
	char *delim = NULL;
	char *value_start = NULL;

	g_return_val_if_fail (header != NULL, NULL);

	delim = g_strrstr (header, ": ");
	value_start = delim + 2;

	if (delim == NULL)
		return NULL;

	msgheader = g_new (MessageHeader, 1);
	msgheader->name = g_strndup (header, delim - header);
	msgheader->value = g_strdup (value_start);

	return msgheader;
}

void
message_header_free (MessageHeader *header)
{
	g_return_if_fail (header != NULL);

	if (header->name != NULL)
		g_free (header->name);

	if (header->value != NULL)
		g_free (header->value);

	g_free (header);

	return;
}

void
message_headers_free (GSList *list)
{
	MessageHeader *header = NULL;

	g_return_if_fail (list != NULL);

	while (list != NULL) {
		header = list->data;
		if (header == NULL)
			break;
		message_header_free (header);
		list = g_slist_next (list);
	}

	g_slist_free (list);

	return;
}


char *
msn_message_build_new_string (char type, int trid, char *payload, const char *header_format, ...)
{
	va_list args;
    char *header_str = NULL;
	char *msg_body = NULL;
	char *message = NULL;
	int length = 0;

    g_return_val_if_fail (header_format != NULL, NULL);

    va_start (args, header_format);
    header_str = g_strdup_vprintf (header_format, args);
    va_end (args);
	
	msg_body = g_strdup_printf ("%s\r\n%s", header_str, payload);
	length = strlen (msg_body);
	message = g_strdup_printf ("MSG %d %c %i\r\n%s", trid, type, length, msg_body); 
	
	g_free (header_str);
	g_free (msg_body);
	
	return message;
}

MsnMessage *
msn_message_from_string (const char *str)
{
	MsnMessage *msg;
	MsnCommand *msg_cmd;
	GSList *tmp_header = NULL;
	char *content_type = NULL;

	char *body_start = NULL;
	char  **split_body = NULL;   /* Split msg header and body */
	char  **split_headers = NULL;  /* Split header by lines */
	int i = 1;  /* Header iterator */

	g_return_val_if_fail (str != NULL, NULL);

	split_body = g_strsplit (str, "\r\n\r\n", 2);

	if (split_body[0] == NULL) {
		g_strfreev (split_body);
		return NULL;
	}

	split_headers = g_strsplit (split_body[0], "\r\n", 0);

	msg_cmd = msn_command_from_string (split_headers[0]);
	if (msg_cmd == NULL) {
		g_strfreev (split_headers);
		g_strfreev (split_body);
		return NULL;
	}

	if (strcmp ("MSG", msg_cmd->name) != 0) {
		msn_command_free (msg_cmd);
		g_strfreev (split_headers);
		g_strfreev (split_body);
		return NULL;
	}

	if (msg_cmd->params [msg_cmd->param_count - 1] == NULL) {
		msn_command_free (msg_cmd);
		g_strfreev (split_headers);
		g_strfreev (split_body);
		return NULL;
	}

	msg = g_new (MsnMessage, 1);
	msg->length = atoi (msg_cmd->params [msg_cmd->param_count - 1]);

	if (split_body[1] == NULL)
		msg->body = NULL;
	else
		msg->body = g_strdup (split_body[1]);

	msg->headers = NULL;
	while (split_headers [i] != NULL) {
		MessageHeader *header = NULL;
		header = message_header_new (split_headers [i++]);
		msg->headers = g_slist_append (msg->headers, header);
	}

	msg->msg_cmd = g_strdup (split_headers [0]);
	msg->full_msg = g_strdup (str);

	/* Determine content-type */
	tmp_header = msg->headers;
	while (tmp_header != NULL) {
		MessageHeader *h = (MessageHeader *) tmp_header->data;
		if (h == NULL)
			break;

		if (!strcmp (h->name, "Content-Type")) {
			char *data = h->value;
			char *end = strchr (data, ';');

			if (data == NULL)
				break;

			/* Determine if theres other data on the line */
			if (end != NULL)
				content_type = g_strndup (data, end - data);
			else
				content_type = g_strdup (data);
			break;
		}

		tmp_header = g_slist_next (tmp_header);
	}

	msg->content_type = content_type;

	g_strfreev (split_body);
	msn_command_free (msg_cmd);
	g_strfreev (split_headers);

	return msg;
}

void
msn_message_free (MsnMessage *msg)
{
	g_return_if_fail (msg != NULL);

	if (msg->msg_cmd != NULL) {
		g_free (msg->msg_cmd);
		msg->msg_cmd = NULL;
	}

	if (msg->headers != NULL) {
		message_headers_free (msg->headers);
		msg->headers = NULL;
	}

	if (msg->content_type != NULL) {
		g_free (msg->content_type);
		msg->content_type = NULL;
	}

	if (msg->body != NULL) {
		g_free (msg->body);
		msg->body = NULL;
	}

	if (msg->full_msg != NULL) {
		g_free (msg->full_msg);
		msg->full_msg = NULL;
	}

	msg->length = 0;

	return;
}

